#pragma once

#include <iostream>
#include <functional>
using namespace std;

struct Result
{
    string msg = "VALID";
    int result;
};

Result mymath(int x, int y, char op)
{
    Result res;
    int result;
    switch (op)
    {
    case '+':
        res.result = x + y;
        break;
    case '-':
        res.result = x - y;
        break;
    case '*':
        res.result = x * y;
        break;
    case '/':
    {
        if (y == 0)
        {
            cerr << "div zero fault!" << endl;
            res.msg = "div zero fault!";
            res.result = -1;
        }
        else
            res.result = x / y;
    }
    break;
    case '%':
    {
        if (y == 0)
        {
            cerr << "mod zero fault!" << endl;
            res.msg = "mod zero fault!";
            res.result = -1;
        }
        else
            res.result = x % y;
    }
    break;
    default:
        break;
    }

    return res;
}

class CalTask
{
public:
    using func_t = function<Result(int, int, char)>;
    // typedef function<int(int, int, char)> func_t;      // 作用和上面一模一样
public:
    CalTask()
    {
    }

    CalTask(int x, int y, char op, func_t func)
        : _x(x), _y(y), _op(op), _func(func)
    {
    }

    ~CalTask()
    {
    }

    string operator()()
    {
        Result res = _func(_x, _y, _op);
        char taskname[64];
        if (res.msg != "VALID")
            snprintf(taskname, sizeof(taskname), "%d %c %d = %d(%s)", _x, _op, _y, res.result, res.msg.c_str());
        else
            snprintf(taskname, sizeof(taskname), "%d %c %d = %d", _x, _op, _y, res.result);

        return taskname;
    }

    string task_to_string()
    {
        char taskname[64];
        snprintf(taskname, sizeof(taskname), "%d %c %d = ?", _x, _op, _y);
        return taskname;
    }

public:
    int _x;
    int _y;
    char _op;
    func_t _func;
};

void save(const string &message)
{

    FILE *fp = fopen("./log.txt", "a+");
    if (!fp)
    {
        perror("fopen");
        exit(1);
    }

    fputs(message.c_str(), fp);
    fputs("\n", fp);
    fclose(fp);
}

class SaveTask
{
public:
    typedef function<void(string)> func_t;

public:
    SaveTask()
    {
    }

    SaveTask(const string &message, func_t func)
        : _message(message), _func(func)
    {
    }

    void operator()()
    {
        _func(_message);
    }

private:
    string _message;
    func_t _func;
};